package de.haw.gka.a1;


import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;

import org.jgrapht.ext.JGraphModelAdapter;
import org.jgrapht.graph.AbstractGraph;
import org.jgrapht.graph.WeightedPseudograph;

public class Main extends JFrame implements SearchTyps{


	private static final long serialVersionUID = 1L;

	private JMenuBar menubar = new JMenuBar();
	
	private JMenu dateiMenu = new JMenu("Datei");
	private JMenu searchMenu = new JMenu("Suche");
	private JMenu createMenu = new JMenu("Neu");
    private JMenu spannbaumMenu = new JMenu("Spannbaum");
	
	private JMenuItem openItem = new JMenuItem("öffnen");
	private JMenuItem saveItem = new JMenuItem("Speichern");
	private JMenuItem exitItem = new JMenuItem("Beenden");
	private JMenuItem dfsItem = new JMenuItem("Tiefensuche");
	private JMenuItem bfsItem = new JMenuItem("Breitensuche");
	private JMenuItem djktrItem = new JMenuItem("Dijkstra");
	private JMenuItem aSternItem = new JMenuItem("A*");
	private JMenuItem newGraphItem = new JMenuItem("neuer Graph");
	private JMenuItem randomGraphItem = new JMenuItem("Random Graph");

    private JMenuItem kruskalItem = new JMenuItem("Kruskal");
    private JMenuItem primAlgoItem = new JMenuItem("Prim");
    private JMenuItem primAlgoFiboItem = new JMenuItem("Prim Fibo");
    private JMenuItem hierholzerAlgoItem = new JMenuItem("Hierholzer");
    private JMenuItem fleuryAlgoItem = new JMenuItem("Fleury");
	
	private JPanel centerPnl = new JPanel();
	private AbstractGraph graph;
	
	
	public Main(){
		init();
	}
	
	
	public static void main(String[] args){
		new Main();
	}
	
	private void init(){
		actionPerformed();
		
		dateiMenu.add(createMenu);
		dateiMenu.add(new JSeparator());
		dateiMenu.add(openItem);		
		dateiMenu.add(saveItem);
		dateiMenu.add(new JSeparator());
		dateiMenu.add(exitItem);
		searchMenu.add(bfsItem);
		searchMenu.add(dfsItem);
		searchMenu.add(new JSeparator());
        searchMenu.add(djktrItem);
		searchMenu.add(aSternItem);

        spannbaumMenu.add(kruskalItem);
        spannbaumMenu.add(primAlgoItem);
        spannbaumMenu.add(primAlgoFiboItem);
        spannbaumMenu.add(new JSeparator());
        spannbaumMenu.add(hierholzerAlgoItem);
        spannbaumMenu.add(fleuryAlgoItem);
		
		createMenu.add(newGraphItem);
		createMenu.add(randomGraphItem);
		
		menubar.add(dateiMenu);
		menubar.add(searchMenu);
        menubar.add(spannbaumMenu);

		this.setJMenuBar(menubar);
		this.getContentPane().add(centerPnl, BorderLayout.CENTER);
		this.setSize(1000,850);
		this.setVisible(true);		
	}
		
	public void actionPerformed(){

		openItem.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
		        try {
					openAction(e);
				} catch (FileNotFoundException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}				
			}
		});

		saveItem.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				saveAction(e);				
			}
		});
		
		exitItem.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				exitAction(e);
			}
		});

		fleuryAlgoItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            	fleuryAction(e);
            }


        });
        hierholzerAlgoItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            	hierholzerAction(e);
            }


        });
        primAlgoFiboItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                primFiboAction(e);
            }


        });

        primAlgoItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                primAction(e);
            }
        });
        kruskalItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                kruskalAction(e);
            }
        });

		dfsItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
					dfsAction(e);			
			}
		});
		bfsItem.addActionListener(new ActionListener() {			
			public void actionPerformed(ActionEvent e) {
				bfsAction(e);				
			}
		});
		aSternItem.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				if(!(graph instanceof WeightedPseudograph)){
					JOptionPane.showMessageDialog(null, "Es wurde kein Gewichteter Graph übergeben!","Fehler...", JOptionPane.ERROR_MESSAGE);
				}else{
					aSternAction(e);
				}
				
			}
		});
		
		randomGraphItem.addActionListener(new ActionListener() {			
			@Override
			public void actionPerformed(ActionEvent e) {
				createRandomAction(e);
			}
		});

        djktrItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                djsktraAction(e);
            }
        });
		
	}

    void fleuryAction(ActionEvent e){
	    new SearchDia(fleury, graph).setMainFrame(this);
	}
	void hierholzerAction(ActionEvent e){
	    new SearchDia(hierholzer, graph).setMainFrame(this);
	}
    void primAction(ActionEvent e) {
        new SearchDia(prim, graph).setMainFrame(this);
    }

    void primFiboAction(ActionEvent e){
        new SearchDia(primFibo, graph).setMainFrame(this);
    }

    void kruskalAction(ActionEvent e){
        new SearchDia(kruskal, graph).setMainFrame(this);
    }
	
	void createRandomAction(ActionEvent e){
		CreateDia.getInstance(random, this);
	}
	
	void dfsAction(ActionEvent e){		
		new SearchDia(dfs, graph).setMainFrame(this);		
	}
	
	void bfsAction(ActionEvent e){		
		 new SearchDia(bfs, graph).setMainFrame(this);		
	}
	
	void djsktraAction(ActionEvent e){
		new SearchDia(djktra, graph).setMainFrame(this);
	}
	
	void aSternAction(ActionEvent e){
		new SearchDia(astern, graph).setMainFrame(this);
	}
	
	void openAction(ActionEvent e) throws FileNotFoundException, IOException{		
		JFileChooser openFileChooser = new JFileChooser();
		openFileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
		int klickAction = openFileChooser.showDialog(this, "Öffnen");
		if(klickAction == openFileChooser.APPROVE_OPTION){
            File file = openFileChooser.getSelectedFile();
			AbstractGraph<?, ?> tgraph = ReadFile.getInstance().getGraph(file.getAbsolutePath());
			int ecken = ReadFile.getInstance().getAnzahlEcken();
			addGraph(tgraph, ecken, file.getName());			
		}		
	}
	
	public void addGraph(AbstractGraph<?, ?> aGraph, int kanten , String titel){
		this.remove(centerPnl);
		this.graph = aGraph;
		if(kanten > 28){
			JOptionPane.showMessageDialog(this, "Der Graph ist zu Groß um ihn zu visualisieren,\n" +
					"Der Graph wurde aber um Programm hinzugefüht!", "Info...", JOptionPane.INFORMATION_MESSAGE);
			return;
		}  else{
            centerPnl = new ViewGraph(titel, aGraph, kanten);
        }

		this.getContentPane().add(centerPnl, BorderLayout.CENTER);
		this.validate();
	}

    public void updateGraph(AbstractGraph<?,?> abstractGraph, int kanten, String titel, JGraphModelAdapter<?,?> adapter){
        this.remove(centerPnl);
        this.graph = abstractGraph;
        if(kanten > 28){
            JOptionPane.showMessageDialog(this, "Der Graph ist zu Groß um ihn zu visualisieren,\n" +
                    "Der Graph wurde aber um Programm hinzugefüht!", "Info...", JOptionPane.INFORMATION_MESSAGE);
              return;
        } else
            centerPnl = new ViewGraph(titel, abstractGraph, kanten, adapter);
        this.getContentPane().add(centerPnl, BorderLayout.CENTER);
        this.validate();
    }
	
	void saveAction(ActionEvent e){		
		JFileChooser saveFileChooser = new JFileChooser();
		saveFileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
		int klickAction = saveFileChooser.showDialog(this, "Speichern");
		if(klickAction == saveFileChooser.APPROVE_OPTION){
			if(graph == null) {
				JOptionPane.showMessageDialog(this, "Es wurde noch kein Graph zum Speichern geladen","Error", JOptionPane.ERROR_MESSAGE);
				return;
			}			
			File file = saveFileChooser.getSelectedFile();			
			if(new SaveGraph().save(file.getAbsolutePath(), graph)){
				JOptionPane.showMessageDialog(this, "Speicherung Erfolgreich!","Happy Birthday", JOptionPane.INFORMATION_MESSAGE);
			}else{
				JOptionPane.showMessageDialog(null, "Speicherung fehlgeschlagen!", "Error", JOptionPane.ERROR_MESSAGE);
			}
		}
	}	
		
	void exitAction(ActionEvent e){
		System.exit(0);
	}


	
}
